﻿/********************************************************************************
* Copyright 2010 Zane Thorn (zane.thorn@gmail.com)                              *
*                                                                               *
* NeturalMath is free software: you can redistribute it and/or modify           *
* it under the terms of the GNU Lesser General Public License as published by   *
* the Free Software Foundation, either version 3 of the License, or             *
* (at your option) any later version.                                           *
*                                                                               *
* NeturalMath is distributed in the hope that it will be useful,                *
* but WITHOUT ANY WARRANTY; without even the implied warranty of                *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
* GNU Lesser General Public License for more details.                           *
*                                                                               *
* You should have received a copy of the GNU Lesser General Public License      *
* along with NeturalMath.  If not, see <http://www.gnu.org/licenses/>.          *
********************************************************************************/

using System;

namespace NeturalMath
{
    /// <summary>
    /// The data type used internally by Netural Math to represent a true or false value
    /// </summary>
    public sealed class BooleanValue:MathValue
    {
        /// <summary>
        /// Used internally to create an instance of a boolean value.  Should only be used to create the Runtime.True and Runtime.False constants
        /// </summary>
        /// <param name="value"></param>
        internal BooleanValue(bool value,MathRuntime runtime)
            :base(ValueTypes.Bool,"bool",value,runtime)
        {
            Value = value;
        }

        /// <summary>
        /// Overrides the base Value property with a boolean value
        /// </summary>
        public new bool Value { get; private set; }

        #region Basic Math Functions

        /// <summary>
        /// Overrides basic Add functionality.
        /// </summary>
        /// <remarks>
        /// Logic Table
        /// # 0 1
        /// 0 0 1
        /// 1 1 1
        /// </remarks>
        /// <param name="arg">The value to be added</param>
        /// <returns>The Sum of the two values</returns>
        protected override MathValue Add(MathValue arg)
        {
            // Logic Table
            // # 0 1
            // 0 0 1
            // 1 1 0
            var other = (BooleanValue)arg;
            var result = Value ^ other.Value;
            return Runtime.NewBool(result);
        }

        /// <summary>
        /// Overrides basic Subtract functionality.
        /// </summary>
        /// <remarks>
        /// # 0 1
        /// 0 0 0
        /// 1 1 0
        /// </remarks>
        /// <param name="arg">The value to be subtracted</param>
        /// <returns>The difference between the two values</returns>
        protected override MathValue Subtract(MathValue arg)
        {
            // Logic Table
            // # 0 1
            // 0 0 1
            // 1 1 0
            var other = (BooleanValue)arg;
            var result = Value ^ other.Value;
            return Runtime.NewBool(result);
        }

        /// <summary>
        /// Overrides basic Multiply functionality.
        /// </summary>
        /// <remarks>
        /// # 0 1
        /// 0 0 0
        /// 1 0 1
        /// </remarks>
        /// <param name="arg">The value to be multiplied</param>
        /// <returns>The product between the two values</returns>
        protected override MathValue Multiply(MathValue arg)
        {
            // Logic Table
            // # 0 1
            // 0 0 0
            // 1 0 1
            var other = (BooleanValue)arg;
            var result = Value && other.Value;
            return Runtime.NewBool(result);
        }

        /// <summary>
        /// Overrides basic Divide functionality.
        /// </summary>
        /// <remarks>
        /// # 0 1
        /// 0 X 0
        /// 1 X 1
        /// </remarks>
        /// <param name="arg">The value to be divided by</param>
        /// <returns>The dividand between the two values</returns>
        protected override MathValue Divide(MathValue arg)
        {
            // Logic Table
            // # 0 1
            // 0 X 0
            // 1 X 1
            var other = (BooleanValue)arg;
            return other.Value ? Runtime.NewBool(Value) : Runtime.Undefined;
        }

        /// <summary>
        /// Overrides basic Modulo functionality.
        /// </summary>
        /// <remarks>
        /// # 0 1
        /// 0 X 0
        /// 1 X 0
        /// </remarks>
        /// <param name="arg">The value to be divided by</param>
        /// <returns>The remainder between the two values</returns>
        protected override MathValue Modulo(MathValue arg)
        {
            // Logic Table
            // # 0 1
            // 0 X 0
            // 1 X 0
            var other = (BooleanValue)arg;
            return other.Value ? Runtime.False : Runtime.Undefined;
        }

        /// <summary>
        /// Overrides basic Power functionality.
        /// </summary>
        /// <param name="arg">The value to be raised by</param>
        /// <returns>The exponent of the two values</returns>
        protected override MathValue Power(MathValue arg)
        {
            // Logic Table
            // # 0 1
            // 0 1 0
            // 1 1 1
            var other = (BooleanValue)arg;
            return (!other.Value) ? Runtime.True : Runtime.NewBool(Value);
        }

        #endregion

        #region Comparision Functions

        /// <summary>
        /// Overrides base functionality
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        protected override bool? IsLessThan(MathValue arg)
        {
            var val = (bool)arg.Value;
            if (!Value && val)
                return true;
            return false;
        }


        /// <summary>
        /// Overrides base functionality
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        protected override bool? IsGreaterThan(MathValue arg)
        {
            var val = (bool)arg.Value;
            if (Value && !val)
                return true;
            return false;
        }


        #endregion

        #region Logical Operators

        /// <summary>
        /// Overrides base functionality
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        protected override MathValue And(MathValue arg)
        {
            var other = (BooleanValue)arg;
            return Runtime.NewBool(Value && other.Value);
        }

        /// <summary>
        /// Overrides base functionality
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        protected override MathValue Or(MathValue arg)
        {
            var other = (BooleanValue)arg;
            return Runtime.NewBool(Value || other.Value);
        }

        /// <summary>
        /// Overrides base functionality
        /// </summary>
        /// <param name="arg"></param>
        /// <returns></returns>
        protected override MathValue Xor(MathValue arg)
        {
            var other = (BooleanValue)arg;
            return Runtime.NewBool(Value ^ other.Value);
        }

        #endregion

        #region Converstion Functions

        /// <summary>
        /// Flips the boolean value
        /// </summary>
        /// <returns></returns>
        protected override MathValue Flip()
        {
            return Runtime.NewBool(!Value);
        }

        /// <summary>
        /// Converts the current value to a string
        /// </summary>
        /// <returns>A string representation of the value</returns>
        protected internal override MathValue ConvertToString()
        {
            return Value ? Runtime.TrueString : Runtime.FalseString;
        }

        /// <summary>
        /// Converts the value to a number
        /// </summary>
        /// <returns>The numeric data for the value</returns>
        protected internal override MathValue ConvertToNumber()
        {
            return (NumberValue)(Value ? Runtime.One : Runtime.Zero);
        }

        /// <summary>
        /// Converts the value to a boolean
        /// </summary>
        /// <returns></returns>
        protected internal override MathValue ConvertToBoolean()
        {
            return this;
        }

        /// <summary>
        /// Converts the value to a range
        /// </summary>
        /// <returns></returns>
        protected internal override MathValue ConvertToRange()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Converts the value to a complex
        /// </summary>
        /// <returns></returns>
        protected internal override MathValue ConvertToComplex()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Converts the value to a unit, based on the specified unit measure
        /// </summary>
        /// <param name="measure"></param>
        /// <returns></returns>
        protected internal override MathValue ConvertToUnit(Units.UnitMeasure measure)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Converts the provided value into a BooleanValue
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        protected override MathValue ConvertToNativeValue(MathValue value)
        {
            if (value == null)
                return Runtime.False;

            return value.ConvertToBoolean();
        }

        /// <summary>
        /// Overrides base functionality
        /// </summary>
        /// <returns></returns>
        protected override bool IsTrue()
        {
            return Value;
        }


        /// <summary>
        /// Overrides base functionality
        /// </summary>
        /// <returns></returns>
        protected override MathValue ToMinus()
        {
            return Runtime.NewBool(!Value);
        }

        

        #endregion

        /// <summary>
        /// Overrides the get to string functionality to return true or false
        /// </summary>
        /// <returns></returns>
        protected override string GetToString()
        {
            return Value ? "true" : "false";
        }

        

        

        

        
    }
}
